package com.算法.操作系统;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;

public class MyJFrame {
    public static void main(String[] args) {
        My_Main();
    }
    public static void My_Main() {
        JFrame jFrame = new JFrame("进程调度模拟系统");
        JPanel contentPane = new JPanel(new GridBagLayout());
        jFrame.setContentPane(contentPane);

        GridBagConstraints gbc = new GridBagConstraints();
        // 调整登录界面字体下面的空白行高度
        gbc.insets = new Insets(20, 30, 20, 30);

        JPanel loginPanel = new JPanel(new GridBagLayout());
        loginPanel.setBackground(Color.LIGHT_GRAY);
//        loginPanel.setBackground(Color.WHITE);
        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.gridwidth = 1;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        JLabel lb1_login = new JLabel("登录界面", SwingConstants.CENTER);
        lb1_login.setFont(new Font("楷体", Font.PLAIN, 46));
//        lb1_login.setFont(new Font("宋体", Font.PLAIN, 40));
        loginPanel.add(lb1_login, gbc);

        JPanel inputPanel = new JPanel(new GridBagLayout());
        inputPanel.setBackground(Color.WHITE);

        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.gridwidth = 1;
        JLabel lb2_name = new JLabel("账号");
        lb2_name.setFont(new Font("宋体", Font.PLAIN, 24));
        inputPanel.add(lb2_name, gbc);

        // 账号输入框
        gbc.gridx = 1;
        gbc.gridwidth = 2; // 设置宽度跨越两列
        JTextField usernameField = new JTextField(20);
        usernameField.setPreferredSize(new Dimension(230, 40)); // 修改输入框尺寸
        usernameField.setFont(new Font("宋体", Font.PLAIN, 20));
        inputPanel.add(usernameField, gbc);

        // 密码输入框
        gbc.gridx = 0;
        gbc.gridy = 1;
        gbc.gridwidth = 1;
        JLabel lb3_pwd = new JLabel("密码");
        lb3_pwd.setFont(new Font("宋体", Font.PLAIN, 24));
        inputPanel.add(lb3_pwd, gbc);

        gbc.gridx = 1;
        gbc.gridwidth = 2; // 设置宽度跨越两列
        JPasswordField passwordField = new JPasswordField(20);
        passwordField.setPreferredSize(new Dimension(230, 40)); // 修改输入框尺寸
        passwordField.setFont(new Font("宋体", Font.PLAIN, 20));
        inputPanel.add(passwordField, gbc);

        JButton loginButton = new JButton("登录");
        loginButton.setPreferredSize(new Dimension(170, 40));
        loginButton.setFont(new Font("宋体", Font.PLAIN, 20));
        gbc.gridx = 0;
        gbc.gridy = 2;
        gbc.gridwidth = 1;
        inputPanel.add(loginButton, gbc);

        JButton cancelButton = new JButton("取消登录");
        cancelButton.setPreferredSize(new Dimension(230, 40));
        cancelButton.setFont(new Font("宋体", Font.PLAIN, 20));
        gbc.gridx = 1;
        inputPanel.add(cancelButton, gbc);

        // 登录监听事件
        loginButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                login_verify(jFrame, usernameField, passwordField);
            }
        });
        // 取消登录监听事件
        cancelButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                // 将输入框的值设置为null
                usernameField.setText("");
                passwordField.setText("");
            }
        });
        //键盘监听事件:
        usernameField.setFocusable(true);
        usernameField.requestFocusInWindow();
        usernameField.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                int keyCode = e.getKeyCode();
                if (keyCode == KeyEvent.VK_ENTER) {
                    login_verify(jFrame, usernameField, passwordField);
                    System.out.println("按下回车键");
                }
            }
        });
        //键盘监听事件:
        passwordField.setFocusable(true);
        passwordField.requestFocusInWindow();
        passwordField.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                int keyCode = e.getKeyCode();
                if (keyCode == KeyEvent.VK_ENTER) {
                    login_verify(jFrame, usernameField, passwordField);
                    System.out.println("按下回车键");
                }
            }
        });
        gbc.gridx = 0;
        gbc.gridy = 1;
        gbc.gridwidth = 1;
        gbc.insets = new Insets(1, 1, 40, 0); // 调整下方的空白行高度
        contentPane.add(loginPanel, gbc);
        gbc.gridy = 2;
        contentPane.add(inputPanel, gbc);

        jFrame.setSize(800, 600);
        jFrame.setVisible(true);
        jFrame.setLocationRelativeTo(null);
        jFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        jFrame.setResizable(false);
    }
    public static void procss_system(){
        // JTattoo 美化包
        JFrame.setDefaultLookAndFeelDecorated(true);
        try {
            String lookAndFeel = "com.jtattoo.plaf.hifi.HiFiLookAndFeel";
            UIManager.setLookAndFeel(lookAndFeel);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (UnsupportedLookAndFeelException e) {
            e.printStackTrace();
        }

        Queue readyQueue = new Queue();
        Queue blockedQueue = new Queue();
        Scheduling_Algorithm tsc = new Scheduling_Algorithm();
        JTextArea textArea = new JTextArea();

        // 创建主窗口
        JFrame newFrame = new JFrame("进程调度模拟系统");
        JPanel newContentPane = new JPanel(new BorderLayout());
        JLabel lb1 = new JLabel("欢迎进入进程调度模拟系统");
        lb1.setHorizontalAlignment(SwingConstants.CENTER);
        lb1.setFont(new Font("宋体", Font.ITALIC, 38));

        JPanel topPanel = new JPanel(new BorderLayout());
        topPanel.add(lb1, BorderLayout.NORTH);

        // 创建放置下拉框和按钮的面板
        JPanel comboBoxPanel = new JPanel(new FlowLayout(FlowLayout.LEFT)); // 左对齐的流式布局
        // 创建放置label
        String[] options = {"【TRR】算法", "【SPF】算法"};
        JComboBox<String> comboBox = new JComboBox<>(options);
        comboBox.setFont(new Font("宋体", Font.ITALIC, 22));
        comboBox.setSelectedIndex(0);

        // 创建按钮
        JButton button = new JButton("执行");
        button.setFont(new Font("宋体", Font.PLAIN, 22));
        button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                // 获得下拉框的值
                String selectedOption = (String) comboBox.getSelectedItem();
                // 将选中的选项追加到文本域
                if (!readyQueue.isEmpty()) {
                    if(selectedOption.equals("【TRR】算法")){
                            String input = JOptionPane.showInputDialog("请输入时间片:");
                            if (input != null) {
                                if(input.equals("")){
                                    JOptionPane.showMessageDialog(newFrame,"未输入时间片！", "错误" ,JOptionPane.ERROR_MESSAGE);
                                }else{
                                    textArea.append("\n 选择算法为："+selectedOption + "\n");
                                    int timeSlice = Integer.parseInt(input);
                                    tsc.TRR(readyQueue, blockedQueue, timeSlice, textArea);
                                }
                            } else {
                                textArea.append("\n 取消TRR执行!\n");
                            }
                    }else if(selectedOption.equals("【SPF】算法")){
                        textArea.append("\n 选择算法为："+selectedOption + "\n");
                        // 按照短作业大小进行排序
                        readyQueue.sortBySizeDescending();
                        // textArea.append("默认CPU已经存在一个进程在运行\n");
                        tsc.SPF(readyQueue, blockedQueue, textArea);
                    }else{
                        textArea.append("\n选择错误，请重新选择!\n");
                    }
                }else{
                    JOptionPane.showMessageDialog(newFrame,"当前队列已空请重新加入进程信息！", "错误" ,JOptionPane.ERROR_MESSAGE);
                }
            }
        });

        JButton button1 = new JButton("清空队列");
        button1.setFont(new Font("宋体", Font.PLAIN, 22));
        button1.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                int option = JOptionPane.showConfirmDialog(null, "确认清空队列？", "清空确认", JOptionPane.YES_NO_OPTION);
                if (option == JOptionPane.YES_OPTION) {
                    readyQueue.clear();
                    blockedQueue.clear();
                }
            }
        });

        JButton button_s = new JButton("执行序列");
        button_s.setMinimumSize(new Dimension(60, 40));
        button_s.setFont(new Font("宋体", Font.PLAIN, 22));
        button_s.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                // 创建临时队列，复制原队列元素到临时队列
                Queue tempQueue = new Queue();
                Node currentNode = readyQueue.front;
                while (currentNode != null) {
                    tempQueue.enqueue(currentNode.data); // 复制节点数据到临时队列
                    currentNode = currentNode.next; // 移动到下一个节点
                }
                // 获得下拉框的值
                String selectedOption = (String) comboBox.getSelectedItem();
                if(readyQueue.isEmpty()){
                    JOptionPane.showMessageDialog(newFrame,"就绪队列暂时无作业或无进程！", "错误" ,JOptionPane.ERROR_MESSAGE);
                }else {
                    if(selectedOption.equals("【TRR】算法")){
                        String paixu = QueueSort(readyQueue);
                        textArea.append("\n TRR算法 执行顺序为：" + paixu + "\n");
                    }else if(selectedOption.equals("【SPF】算法")){
                        tempQueue.sortBySizeDescending(); // 按执行时间从小到大排序
                        String paixu = QueueSort(tempQueue);
                        textArea.append("\n SPF算法 执行顺序为：" + paixu + "\n");
                    }else{
                        textArea.append("\n 选择错误，请重新选择!\n");
                    }
                }
            }
        });

        JButton button2 = new JButton("添加PCB信息");
        button2.setFont(new Font("宋体", Font.PLAIN, 22));
        button2.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                JDialog dialog = createProcessInputDialog(newFrame, readyQueue, textArea);
                dialog.setVisible(true);
            }
        });

        JLabel label_text = new JLabel("  请选择调度算法：");
        label_text.setHorizontalAlignment(SwingConstants.CENTER);
        label_text.setFont(new Font("宋体", Font.PLAIN, 24));
        // 新的面板，用于放置底部的按钮
        JPanel bottomPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
        JButton anotherButton = new JButton("清空域");
        anotherButton.setFont(new Font("宋体", Font.PLAIN, 22));
        anotherButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                int option = JOptionPane.showConfirmDialog(null, "确认清空文本域？", "清空确认", JOptionPane.YES_NO_OPTION);
                if (option == JOptionPane.YES_OPTION) {
                    textArea.setText("");
                }
            }
        });
        bottomPanel.add(anotherButton); // 将按钮添加到新的面板中
        newContentPane.add(bottomPanel, BorderLayout.EAST);

        // 将下拉框和按钮添加到面板
        comboBoxPanel.add(button2);
        comboBoxPanel.add(label_text);
        comboBoxPanel.add(comboBox);
        comboBoxPanel.add(button);
        comboBoxPanel.add(button1);
        comboBoxPanel.add(button_s);

        // 将放置下拉框和按钮的面板添加到顶部面板
        topPanel.add(comboBoxPanel, BorderLayout.CENTER);
        newContentPane.add(topPanel, BorderLayout.NORTH);
        // 创建文本域及滚动条
        textArea.setFont(new Font("宋体", Font.PLAIN, 22));
        textArea.setEditable(false);
        JScrollPane scrollPane = new JScrollPane(textArea);

        // 将文本域及滚动条添加到内容面板的中间位置
        newContentPane.add(scrollPane, BorderLayout.CENTER);
        // 设置主窗口的内容面板、大小、位置、关闭行为并显示
        newFrame.setContentPane(newContentPane);
        newFrame.setSize(1400, 900);
        newFrame.setLocationRelativeTo(null);
        newFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        newFrame.setVisible(true);
//        newFrame.setResizable(false);
    }
    public static void login_verify(JFrame jFrame, JTextField usernameField,JPasswordField passwordField){
        // 获取用户名
        String username = usernameField.getText();
        // 获取密码
        char[] passwordChars = passwordField.getPassword();
        String password = new String(passwordChars);
        if(username.equals("admin") && password.equals("admin")){
            System.out.println("登录成功！");
            // 跳转界面，关闭当前窗口
            // 关闭当前窗口
            jFrame.dispose();
            procss_system();
        }else{
            if(!username.equals("admin")){
                if(password.equals("")){
                    JOptionPane.showMessageDialog(jFrame,"账号不能为空！", "错误" ,JOptionPane.WARNING_MESSAGE);
                }else{
                    JOptionPane.showMessageDialog(jFrame,"账号有误错！", "错误" ,JOptionPane.WARNING_MESSAGE);
                }
            }else if(!password.equals("admin")){
                if(password.equals("")){
                    JOptionPane.showMessageDialog(jFrame,"密码不能为空！", "错误" ,JOptionPane.WARNING_MESSAGE);
                }else{
                    JOptionPane.showMessageDialog(jFrame,"密码有误！", "错误" ,JOptionPane.WARNING_MESSAGE);
                }
            }else{
                JOptionPane.showMessageDialog(jFrame,"账号或密码有误！", "错误" ,JOptionPane.ERROR_MESSAGE);
            }
            usernameField.setText("");
            passwordField.setText("");
        }
    }
    public static String QueueSort(Queue readyQueue){
        int s = readyQueue.size();
        StringBuilder str = new StringBuilder();
        for (int i = 0; i < s; i++) {
            PCB pcb = readyQueue.front();
            str.append(pcb.getName()).append("-->");
            readyQueue.enqueue(readyQueue.dequeue()); // 将队列中的 PCB 出队再入队，循环移动队列首部元素
        }
        int lastIndex = str.lastIndexOf("-->");
        if (lastIndex != -1) {
            str.delete(lastIndex, str.length()); // 删除最后一个 "-->"
        }
        return str.toString();
    }
    public static JDialog createProcessInputDialog(JFrame parent, Queue readyQueue, JTextArea textArea) {
        JDialog dialog = new JDialog(parent, "输入进程信息", true);
        dialog.setLayout(new GridLayout(5, 2));
        JTextField nameField = new JTextField();
        nameField.setFont(new Font("宋体", Font.PLAIN, 20));
        JTextField priorityField = new JTextField();
        priorityField.setFont(new Font("宋体", Font.PLAIN, 20));
        JTextField arrivalTimeField = new JTextField();
        arrivalTimeField.setFont(new Font("宋体", Font.PLAIN, 20));
        JTextField remainingTimeField = new JTextField();
        remainingTimeField.setFont(new Font("宋体", Font.PLAIN, 20));
        JLabel Labelname = new JLabel("进程名称:");
        Labelname.setFont(new Font("楷体", Font.PLAIN, 20));
        dialog.add(Labelname);
        dialog.add(nameField);
        JLabel LabelP = new JLabel("优先级 (1-10):");
        LabelP.setFont(new Font("楷体", Font.PLAIN, 20));
        dialog.add(LabelP);
        dialog.add(priorityField);
        JLabel Labelr = new JLabel("到达时间：");
        Labelr.setFont(new Font("楷体", Font.PLAIN, 20));
        dialog.add(Labelr);
        dialog.add(arrivalTimeField);
        JLabel Labelz = new JLabel("执行时间：");
        Labelz.setFont(new Font("楷体", Font.PLAIN, 20));
        dialog.add(Labelz);
        dialog.add(remainingTimeField);
        JButton okButton = new JButton("确定");
        okButton.addActionListener(e -> {
            if(!nameField.getText().equals("") && !arrivalTimeField.getText().equals("") && !remainingTimeField.getText().equals("")){
                int priority = 0;
                int arrivalTime = 0;
                int remainingTime = 0;
                try{
                    // 创建并显示自定义对话框
                    if (textArea.getText().isEmpty()) {
                        textArea.append(" |--------------------------------------------------------------|\n");
                        String output_h = String.format(" | %-8s | %-10s | %-9s | %-9s |%s",
                                "进程名称", "优先级(1-10)", "到达时间[ms]", "执行时间[ms]","\n");
                        textArea.append(output_h);
                        textArea.append(" |--------------------------------------------------------------|\n");
                    }
                    // 读取文本框中的信息
                    String name = nameField.getText();
                    if(!priorityField.getText().equals("")){
                        priority = Integer.parseInt(priorityField.getText());
                    }
                    arrivalTime = Integer.parseInt(arrivalTimeField.getText());
                    remainingTime = Integer.parseInt(remainingTimeField.getText());
                    String output = String.format(" | %-12s | %-13s | %-13s | %-13s |\n",
                            name, priority, arrivalTime, remainingTime);
                    textArea.append(output);
                    textArea.append(" |--------------------------------------------------------------|\n");

                    // 创建新的进程对象并添加到队列
                    PCB process = new PCB();
                    process.setName(name);
                    process.setPriority(priority);
                    process.setArrivalTime(arrivalTime);
                    process.setRemainingTime(remainingTime);
                    process.setUsedCPUTime(0);
                    readyQueue.enqueue(process);
                    // 关闭对话框
                    dialog.dispose();
                }catch (Exception e1){
                    e1.getMessage();
                    JOptionPane.showMessageDialog(dialog,"时间栏请输入整数类型！", "错误" ,JOptionPane.WARNING_MESSAGE);
                }
            }else{
                JOptionPane.showMessageDialog(dialog,"必填项不能为空！", "错误" ,JOptionPane.WARNING_MESSAGE);
            }
        });
        // 文本框的 KeyListener 监听回车键
        nameField.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                int key = e.getKeyCode();
                if (key == KeyEvent.VK_ENTER) {
                    okButton.doClick(); // 模拟点击确定按钮
                }
            }
        });

        // 优先级文本框的 KeyListener 监听回车键
        priorityField.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                int key = e.getKeyCode();
                if (key == KeyEvent.VK_ENTER) {
                    okButton.doClick(); // 模拟点击确定按钮
                }
            }
        });

        // 到达时间文本框的 KeyListener 监听回车键
        arrivalTimeField.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                int key = e.getKeyCode();
                if (key == KeyEvent.VK_ENTER) {
                    okButton.doClick(); // 模拟点击确定按钮
                }
            }
        });

        // 执行时间文本框的 KeyListener 监听回车键
        remainingTimeField.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                int key = e.getKeyCode();
                if (key == KeyEvent.VK_ENTER) {
                    okButton.doClick(); // 模拟点击确定按钮
                }
            }
        });
        JButton cancelButton = new JButton("取消");
        cancelButton.addActionListener(e -> {
            textArea.append("\n 本次输入取消！\n");
            dialog.dispose(); // 关闭对话框
        });
        dialog.add(okButton);
        dialog.add(cancelButton);
        dialog.setSize(400, 300);
        dialog.setLocationRelativeTo(parent);
        return dialog;
    }
}